# -*- coding:utf-8 -*-

import xlrd
from task.settings import ROLLBACK_MODULES,ALTERATION_MODULES,CHECKING_MODULES


class Base(object):

    def __init__(self, zone_file, interface_file, device_file):
        self.zone_file = zone_file
        self.interface_file = interface_file
        self.device_file = device_file
        # 变更步骤输出文件
        self.alteration_file = '../file_storage/a.txt'
        # 回退步骤输出文件
        self.rollback_file = '../file_storage/a.txt'
        # 验证步骤输出文件
        self.checking_file = '../file_storage/a.txt'

    @staticmethod
    def to_mac_address(value):
        """转化成mac格式地址"""
        i = 0
        ret = ''
        while i <= len(value) - 2:
            if ret == '':
                ret = value[i: i + 2]
            else:
                ret = "".join([ret, ':', value[i: i + 2]])
            i = i + 2
        return ret

    @staticmethod
    def to_output_file(data, file_name):
        """追加结果到文件中"""
        with open(file_name, 'a') as wf:
            #wf.write('\n{}'.format(data.encode('utf-8')))
            wf.write('\n{}'.format(data))
        print("File {} append success..........".format(file_name))

    @staticmethod
    def format_zone(zone, host_wwn, engine_wwn):
        """格式化zone信息"""
        return zone.replace(u'主机wwn', host_wwn).replace(u'盘机端口wwn', engine_wwn)

    def handle(self):
        self.check()
        self.fetch()
        self.set_ctx()
        self.adapt()
        self.output()

    def check(self):
        self.check_file_name()

    def check_file_name(self):
        if not self.zone_file.endswith('.xls'):
            print(u"Zone 文件名后缀非法")
        if not self.interface_file.endswith('.xls'):
            print(u"Interface 文件名后缀非法")
        if not self.device_file.endswith('.xls'):
            print(u"Device 文件名后缀非法")

    # 读取配置文件
    def fetch(self):
        self.fetch_zone()
        self.fetch_interface()
        self.fetch_device()

    def fetch_zone(self):
        """zone信息表"""
        zone_data = xlrd.open_workbook(self.zone_file)
        self.zone_table = zone_data.sheets()[0]
        # zone配置固定在第9列索引8，去掉表头
        self.zone_list = self.zone_table.col_values(8)[1:]
        print(self.zone_list)

    def fetch_interface(self):
        """接口信息表"""
        interface_data = xlrd.open_workbook(self.interface_file)
        self.interface_table = interface_data.sheets()[1]
        # 地址固定在表的第13列，去掉表头
        self.mac_address_list = self.interface_table.col_values(12)[1:]
        print(self.mac_address_list)

    def fetch_device(self):
        """设备信息表"""
        device_data = xlrd.open_workbook(self.device_file)
        self.device_table = device_data.sheets()[0]
        # 交换机设备名称固定在表第1列
        self.device_list = self.device_table.col_values(0)[1:]

    def set_ctx(self):
        self.ip_map = {}
        # 变更步骤相关变量设置
        self.c_sh_zone_names = {}
        self.c_config_zone_names = {}
        self.c_zoneset_members = {}
        # 回退步骤相关变量设置
        self.r_zoneset_names = {}
        self.r_no_zone_names = {}
        # 校验步骤相关变量设置
        self.check_zone_infos = {}

    # 处理数据接口 dispatch
    def adapt(self):
        for index, value in enumerate(self.zone_list):
            zone_info = value
            # 主机wwn单元信息,固定第11列
            host_wwn = self.zone_table.cell_value(index + 1, 10).split('\n')
            # 盘机wwn单元信息，固定最后一列
            engine_wnn = self.zone_table.cell_value(index + 1, -1).split('\n')
            valid_engines = [value for value in engine_wnn if
                             self.to_mac_address(value) in self.mac_address_list]
            # 盘机均无效则跳过
            if len(valid_engines) == 0:
                continue
            # 去重
            valid_engines = list(set(valid_engines))
            for i, host in enumerate(host_wwn):
                mac_addr = self.to_mac_address(host)
                if mac_addr not in self.mac_address_list:
                    continue
                # 获取主机wnn交换机名称和zoning
                mac_index = self.mac_address_list.index(mac_addr)
                switch_name = self.interface_table.cell_value(mac_index + 1, 0)
                host_zoning = self.interface_table.cell_value(mac_index + 1, 14)
                if switch_name in self.device_list:
                    # 获取公共信息
                    sw_index = self.device_list.index(switch_name) + 1
                    vsan = int(self.device_table.cell_value(sw_index, 4))
                    ip = self.device_table.cell_value(sw_index, 3)
                    fabric = self.device_table.cell_value(sw_index, 5)
                    main_sw = self.device_table.cell_value(sw_index, 2)  # 取核心交换机
                    self.ip_map[ip] = {
                        'sw': main_sw,
                        'fabric': fabric,
                        'vsan': vsan
                    }
                    for engine in valid_engines:
                        # 获取盘机端口对应的zoning
                        engine_mac = self.to_mac_address(engine)
                        zoning_index = self.mac_address_list.index(engine_mac)
                        engine_zoning = self.interface_table.cell_value(
                            zoning_index + 1, 14)
                        # 主机和盘机端口对应的zoning必须一致,否则过滤
                        if engine_zoning != host_zoning:
                            continue
                        zone = self.format_zone(zone_info, host, engine) # # 这一步成立
                        self.adapt_alteration(ip, host, engine, zone, vsan)
                        #
                        self.adapt_rollback(ip, zone, vsan)
                        self.adapt_check(ip, zone)

    # 进行变更信息的接入
    def adapt_alteration(self, ip, host, engine, zone, vsan):
        sh_zone_info = u'sh zone name {}\n//Zone not present//'
        format_zone = sh_zone_info.format(zone)
        if self.c_sh_zone_names.get(ip):
            self.c_sh_zone_names[ip].append(format_zone)
        else:
            self.c_sh_zone_names[ip] = [format_zone]
        # 拼接格式
        zone_info = u'zone name {} vsan {}\nmember pwwn {}\nmember pwwn {}'
        # 拼接内容
        zone_name_info = zone_info.format(
            zone, vsan, self.to_mac_address(host), self.to_mac_address(engine))
        if self.c_config_zone_names.get(ip):
            self.c_config_zone_names[ip].append(zone_name_info)
        else:
            self.c_config_zone_names[ip] = [zone_name_info]
        # 回滚的格式
        zoneset_members = u'member {}'.format(zone)
        if self.c_zoneset_members.get(ip):
            self.c_zoneset_members[ip].append(zoneset_members)
        else:
            self.c_zoneset_members[ip] = [zoneset_members]
    # 更烦数据的
    def adapt_rollback(self, ip, zone, vsan):
        no_member_zone = u'no member {}'.format(zone)
        if self.r_zoneset_names.get(ip):
            self.r_zoneset_names[ip].append(no_member_zone)
        else:
            self.r_zoneset_names[ip] = [no_member_zone]

        no_name_zone = u'no zone name {} vsan {}'.format(zone, vsan)
        if self.r_no_zone_names.get(ip):
            self.r_no_zone_names[ip].append(no_name_zone)
        else:
            self.r_no_zone_names[ip] = [no_name_zone]

    # 核查数据 生成数据
    def adapt_check(self, ip, zone):
        check_info = u'sh zone name {}\n//Zone有输出'.format(zone)
        if self.check_zone_infos.get(ip):
            self.check_zone_infos[ip].append(check_info)
        else:
            self.check_zone_infos[ip] = [check_info]

    def output(self):
        # 按照ip顺序排序
        sorted(self.ip_map.keys())
        for k, v in self.ip_map.items():
            sw = v['sw']
            fabric = v['fabric']
            vsan = v['vsan']
            # 拼接
            alteration_data = ALTERATION_MODULES.format(
                ip=k, switch_name=sw,
                zone_infos='\n'.join(self.c_sh_zone_names[k]),
                zone_config='\n'.join(self.c_config_zone_names[k]),
                members='\n'.join(self.c_zoneset_members[k]),
                fabric=fabric, vsan=vsan)
            self.to_output_file(alteration_data, self.alteration_file)
            rollback_data = ROLLBACK_MODULES.format(
                ip=k, switch_name=sw,
                no_zone_infos='\n'.join(self.r_no_zone_names[k]),
                members='\n'.join(self.r_zoneset_names[k]),
                fabric=fabric, vsan=vsan)
            self.to_output_file(rollback_data, self.rollback_file)
            check_data = CHECKING_MODULES.format(
                switch_name=sw, ip=k,
                check_zone_infos='\n'.join(self.check_zone_infos[k]))
            self.to_output_file(check_data, self.checking_file)


if __name__ == '__main__':
    Base(r'C:\Users\Administrator\PycharmProjects\HuaWei\file_use\zone.xls',
         r'C:\Users\Administrator\PycharmProjects\HuaWei\file_use\interface.xls',
         r'C:\Users\Administrator\PycharmProjects\HuaWei\file_use/\device.xls').handle()
